package com.lee.forum.controller;

import com.lee.forum.common.AppResult;
import com.lee.forum.common.ResultCode;
import com.lee.forum.config.AppConfig;
import com.lee.forum.model.User;
import com.lee.forum.services.IUserService;
import com.lee.forum.utils.MD5Util;
import com.lee.forum.utils.StringUtil;
import com.lee.forum.utils.UUIDUtil;
import com.lee.forum.ws.ChatEndpoint;
import com.sun.istack.internal.NotNull;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.HashMap;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: lishuo
 * Date: 2023-09-27
 * Time: 21:59
 */
// 对Controller进行API说明
@Api(tags = "用户接口")
// 日志注解
@Slf4j
@RestController
// 路由映射，一级路由
@RequestMapping("/user")
public class UserController {

    @Resource
    private IUserService userService;

    /**
     * 用户注册
     * @param username 用户名
     * @param nickname 昵称
     * @param password 密码
     * @param passwordRepeat 确认密码
     * @return
     */
    @ApiOperation("用户注册")
    @PostMapping("/register")
    public AppResult register(HttpServletRequest request,
                              @ApiParam("用户名") @RequestParam("username") @NotNull String username,
                              @ApiParam("昵称") @RequestParam("nickname") @NotNull String nickname,
                              @ApiParam("密码") @RequestParam("password") @NotNull String password,
                              @ApiParam("确认密码") @RequestParam("passwordRepeat") @NotNull String passwordRepeat,
                              @ApiParam("验证码") @RequestParam("checkcode") @NotNull String checkcode) {
        // 1.参数效验（已在参数中完成）

        // 2.校验重复密码是否一致
        if (!password.equals(passwordRepeat)) {
            // 打印日志
            log.warn(ResultCode.FAILED_TWO_PWD_NOT_SAME.toString());
            // 返回错信息
            return AppResult.failed(ResultCode.FAILED_TWO_PWD_NOT_SAME);
        }
        // 3.校验验证码是否正确
        HttpSession session = request.getSession(false);
        if (session == null) {
            // 打印日志
            log.error("session不存在");
            // 返回错误信息
            return AppResult.failed(ResultCode.ERROR_SERVICES+"请联系管理员");
        }
        // 测试专用：测试白名单(跳过验证码校验)
        // testSign1 123456
        // testSign2 456789
        if (!username.equals("testSign1") && !username.equals("testSign2")) {
            String existCode = (String) session.getAttribute(AppConfig.CHECKCODE);
            // 忽略大小写比较
            if (!existCode.equalsIgnoreCase(checkcode)) {
                // 返回错误信息
                return AppResult.failed(-1,"验证码校验失败，请重试!");
            }
        }

//        String existCode = (String) session.getAttribute(AppConfig.CHECKCODE);
//        // 忽略大小写比较
//        if (!existCode.equalsIgnoreCase(checkcode)) {
//            // 返回错误信息
//            return AppResult.failed(-1,"验证码校验失败，请重试!");
//        }
        // 4.准备数据
        User user = new User();
        user.setUsername(username);
        user.setNickname(nickname);
        user.setPassword(password);
        // 生成盐
        String salt = UUIDUtil.UUID_32();
        // 生成密文
        String encryptPassword = MD5Util.md5Salt(password,salt);
        user.setSalt(salt);
        user.setPassword(encryptPassword);

        // 5.调用Service层
        userService.createNormalUser(user);
        // 6.返回成功结果
        return AppResult.success();
    }

    /**
     * 用户登录
     * @param username 用户名
     * @param password 密码
     * @return
     */
    @ApiOperation("用户登录")
    @PostMapping("/login")
    public AppResult login(HttpServletRequest request,
                           @ApiParam("用户名") @RequestParam("username") @NotNull String username,
                           @ApiParam("密码") @RequestParam("password") @NotNull String password,
                           @ApiParam("验证码") @RequestParam("checkcode") @NotNull String checkcode) {
        // 0.参数校验（上面注解已完成）
        // 1.校验验证码
        HttpSession session = request.getSession(false);
        if (session == null) {
            // 打印日志
            log.error("session不存在");
            // 返回错误信息
            return AppResult.failed(ResultCode.ERROR_SERVICES+"请联系管理员");
        }
        // 测试专用：测试白名单(跳过验证码校验)
        // lee 123456
        // girl 123456
        // fish 123456
        if (!username.equals("lee") && !username.equals("girl") && !username.equals("fish")) {
            String existCode = (String) session.getAttribute(AppConfig.CHECKCODE);
            // 忽略大小写比较
            if (!existCode.equalsIgnoreCase(checkcode)) {
                // 返回错误信息
                return AppResult.failed(-1,"验证码校验失败，请重试!");
            }
        }

        // 2.调用Service层
        User user = userService.login(username,password);
        // 3.判断user对象是否为空（此时可以省略，因为在service层已经校验过了）
        if (user == null) {
            // 打印日志
            log.warn(ResultCode.FAILED_LOGIN.toString()+"user 对象为 null");
            return AppResult.failed(ResultCode.FAILED_LOGIN);
        }
        // 4.登录成功，将User对象设置到Session作用域中
        session.setAttribute(AppConfig.USER_SESSION_KEY,user);
        // 5.返回结果
        return AppResult.success();
    }

    /**
     * 获取用户信息
     * @param request 请求
     * @param id 用户ID
     * @return
     */
    @ApiOperation("获取用户信息")
    @GetMapping("/info")
    public AppResult<User> getUserInfo(HttpServletRequest request,
                                       @ApiParam("用户id") @RequestParam(value = "id",required = false) Long id) {
        // 定义返回的user对象
        User user = null;
        if (id == null) {
            // 1.如果用户id为空，从session中获取当前登录的用户信息
            HttpSession session = request.getSession(false);
            // 添加了拦截器后，这段逻辑可以去掉了
//            if (session == null || session.getAttribute(AppConfig.USER_SESSION_KEY) == null) {
//                // 如果当前未登录
//                // 打印日志
//                log.warn(ResultCode.FAILED_FORBIDDEN.toString());
//                // 返回错误信息
//                return AppResult.failed(ResultCode.FAILED_FORBIDDEN);
//            }
            // 返回从session中获取的用户信息
            user = (User) session.getAttribute(AppConfig.USER_SESSION_KEY);
        } else {
            // 2.如果id不为空，根据id查询用户信息
            user = userService.selectById(id);
        }
        // 3.判断user对象是否为空
        if (user == null) {
            // 打印日志
            log.warn(ResultCode.FAILED_USER_NOT_EXISTS.toString());
            // 返回错误信息
            return AppResult.failed(ResultCode.FAILED_USER_NOT_EXISTS);
        }
        // 4.返回正常用户信息
        return AppResult.success(user);
    }

    /**
     * 退出登录
     * @param request 请求
     * @return
     */
    @ApiOperation("退出登录")
    @GetMapping("/logout")
    public AppResult logout (HttpServletRequest request) {
        // 1.获取session对象
        HttpSession session = request.getSession(false);
        // 2.检查session是否有效
        if (session != null) {
            // 登录状态下退出，打印日志
            log.info("用户退出成功!");
            session.invalidate();
        }
        // 返回成功响应
        return AppResult.success("退出成功");
    }

    @ApiOperation("修改个人信息")
    @PostMapping("/modifyInfo")
    public AppResult<User> modifyInfo(HttpServletRequest request,
                                @ApiParam("登录名") @RequestParam(value = "username",required = false) String username,
                                @ApiParam("昵称") @RequestParam(value = "nickname",required = false) String nickname,
                                @ApiParam("性别") @RequestParam(value = "gender",required = false) Byte gender,
                                @ApiParam("邮箱") @RequestParam(value = "email",required = false) String email,
                                @ApiParam("手机号") @RequestParam(value = "phoneNum",required = false) String phoneNum,
                                @ApiParam("个人简介") @RequestParam(value = "remark",required = false) String remark) {
        // 1.校验参数
        if (StringUtil.isEmpty(username) && StringUtil.isEmpty(nickname) && gender == null
                && StringUtil.isEmpty(email) && StringUtil.isEmpty(phoneNum) && StringUtil.isEmpty(remark)) {
            // 返回错误信息
            return AppResult.failed("请输入修改信息！");
        }
        // 2.获取当前登录用户
        HttpSession session = request.getSession(false);
        User user = (User) session.getAttribute(AppConfig.USER_SESSION_KEY);
        // 3.封装对象
        User updateUser = new User();
        updateUser.setId(user.getId()); // 设置用户id
        updateUser.setUsername(username); // 设置用户登录名
        updateUser.setNickname(nickname); // 设置昵称
        updateUser.setGender(gender); // 设置性别
        updateUser.setEmail(email); // 设置邮箱
        updateUser.setPhoneNum(phoneNum); // 设置电话号码
        updateUser.setRemark(remark); // 设置个人简介
        // 4.调用Service修改个人信息
        userService.modifyInfo(updateUser);
        // 5.查询最新的用户信息
        user = userService.selectById(user.getId());
        // 6.将最新的用户信息设置到session中
        session.setAttribute(AppConfig.USER_SESSION_KEY,user);
        // 7.返回正确信息
        return AppResult.success(user);
    }

    @ApiOperation("修改密码")
    @PostMapping("/modifyPwd")
    public AppResult modifyPassword (HttpServletRequest request,
                                     @ApiParam("原密码") @RequestParam("oldPassword") @NotNull String oldPassword,
                                     @ApiParam("新密码") @RequestParam("newPassword") @NotNull String newPassword,
                                     @ApiParam("确认密码") @RequestParam("passwordRepeat") @NotNull String passwordRepeat) {
        // 1.判断新密码和确认密码是否相同
        if (!passwordRepeat.equals(newPassword)) {
            // 返回错误信息
            return AppResult.failed(ResultCode.FAILED_TWO_PWD_NOT_SAME);
        }
        // 2.判断新密码和原密码是否相同
        if (oldPassword.equals(newPassword)) {
            // 返回错误信息
            return AppResult.failed("新密码不能与原密码相同！");
        }
        // 2.获取当前登录用户
        HttpSession session = request.getSession(false);
        User user = (User) session.getAttribute(AppConfig.USER_SESSION_KEY);
        // 3.调用service修改密码
        userService.modifyPassword(user.getId(),newPassword,oldPassword);
        // 4.销毁session
        if (session != null) {
            session.invalidate();
        }
        // 5.返回成功信息
        return AppResult.success();
    }


    @ApiOperation("上传头像")
    @PostMapping("/upload")
    public AppResult<User> uploadPhoto(HttpServletRequest request,
            @ApiParam("用户头像") @RequestPart("file") @NotNull MultipartFile file) throws IOException {
        // 获取当前用户
        HttpSession session = request.getSession(false);
        User user = (User) session.getAttribute(AppConfig.USER_SESSION_KEY);
        // 调用service
        User newUser = userService.uploadPhoto(file,user.getId());
        // 返回结果
        return AppResult.success(newUser);
    }

    @ApiOperation("获取验证码")
    @GetMapping("/getcode")
    public AppResult<String> getcode(HttpServletRequest request) {


        // 1.调用service获取验证码
        HashMap<String,String> map = userService.createImage();
        String imageName = map.get("imageName");
        String code = map.get("code");
        // 2.将code存到session中
        HttpSession session = request.getSession();
        session.setAttribute(AppConfig.CHECKCODE,code);
        // 3.返回图形验证码路径给前端
        return AppResult.success(imageName);
    }

    /**
     * 获取当前登录用户基本通讯信息
     * @return
     */
    @ApiOperation("获取当前登录用户基本通讯信息")
    @GetMapping("/getUserInfo")
    public AppResult<User> login(HttpSession httpSession) {
        User user = (User) httpSession.getAttribute(AppConfig.USER_SESSION_KEY);
        return AppResult.success(user);
    }

    /**
     * 获取发信人的基本通讯信息
     * @return
     */
    @ApiOperation("获取发信人的基本通讯信息")
    @GetMapping("/getToUserInfo")
    public AppResult<User> login(@ApiParam("发送人id") @RequestParam(value = "id",required = true) @NotNull Long id) {
        // 调用Service查询
        User user = userService.selectById(id);
        if (user == null) {
            // 打印日志
            log.warn("user 对象为 null");
            return AppResult.failed(ResultCode.ERROR_IS_NULL);
        }

        // 遍历ChatEndpoint结点，判断在线状态
        String isOnline = "false";
        for (User user1 : ChatEndpoint.onlineClient.keySet()) {
            if (user1.getId() == id) {
                isOnline = "true";
                break;
            }
        }

        AppResult<User> appResult = new AppResult<>(200,isOnline,user);
        return appResult;
    }


}
